// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Abilities/GameplayAbility.h"
#include "InteractionOption.generated.h"

class IInteractableTarget;
class UUserWidget;

/**
 * 交互选项结构体，定义交互的各个方面
 */
USTRUCT(BlueprintType)
struct FInteractionOption
{
	GENERATED_BODY()

public:
	/** 可交互目标 */
	UPROPERTY(BlueprintReadWrite)
	TScriptInterface<IInteractableTarget> InteractableTarget; // 交互目标接口

	/** 交互可能返回的简单文本 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FText Text; // 主文本

	/** 交互可能返回的简单子文本 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FText SubText; // 子文本

	// 交互方法
	//--------------------------------------------------------------

	// 1) 在角色上放置一个能力，当执行交互时可以激活

	/** 当角色靠近可交互对象时授予角色的能力 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TSubclassOf<UGameplayAbility> InteractionAbilityToGrant; // 要授予的交互能力类

	// - 或者 -

	// 2) 允许我们交互的对象拥有自己的能力系统和交互能力，我们可以激活它

	/** 目标上的能力系统，可用于TargetInteractionHandle和发送事件（如果需要） */
	UPROPERTY(BlueprintReadOnly)
	TObjectPtr<UAbilitySystemComponent> TargetAbilitySystem = nullptr; // 目标能力系统组件

	/** 在此对象上为此选项激活的能力规格句柄 */
	UPROPERTY(BlueprintReadOnly)
	FGameplayAbilitySpecHandle TargetInteractionAbilityHandle; // 目标交互能力句柄

	// 用户界面
	//--------------------------------------------------------------

	/** 为此类交互显示的小部件 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSoftClassPtr<UUserWidget> InteractionWidgetClass; // 交互小部件类

	//--------------------------------------------------------------

public:
	/**
	 * 等于运算符重载
	 * @param Other 要比较的另一个交互选项
	 * @return 如果两个交互选项相等返回true，否则返回false
	 */
	FORCEINLINE bool operator==(const FInteractionOption& Other) const
	{
		return InteractableTarget == Other.InteractableTarget &&
			InteractionAbilityToGrant == Other.InteractionAbilityToGrant&&
			TargetAbilitySystem == Other.TargetAbilitySystem &&
			TargetInteractionAbilityHandle == Other.TargetInteractionAbilityHandle &&
			InteractionWidgetClass == Other.InteractionWidgetClass &&
			Text.IdenticalTo(Other.Text) &&
			SubText.IdenticalTo(Other.SubText);
	}

	/**
	 * 不等于运算符重载
	 * @param Other 要比较的另一个交互选项
	 * @return 如果两个交互选项不相等返回true，否则返回false
	 */
	FORCEINLINE bool operator!=(const FInteractionOption& Other) const
	{
		return !operator==(Other);
	}

	/**
	 * 小于运算符重载
	 * @param Other 要比较的另一个交互选项
	 * @return 如果当前交互选项小于另一个返回true，否则返回false
	 */
	FORCEINLINE bool operator<(const FInteractionOption& Other) const
	{
		return InteractableTarget.GetInterface() < Other.InteractableTarget.GetInterface();
	}
};